﻿
using Microsoft.FSharp.Collections;

using Plotly.NET;
using Plotly.NET.LayoutObjects;

using System.Text;

namespace UCTT.Net
{
    public partial class Form2 : Form
    {
        #region       变量/常量 start
        /// <summary>
        /// Plotly.js 绘图库的cdn链接
        /// </summary>
        private const string PlotlyJS = "https://cdn.bootcdn.net/ajax/libs/plotly.js/2.27.1/plotly.min.js";
        private const string HtmlTemplate = $"""
            <!DOCTYPE html>
            <html>
                <head>
                    <script src="{PlotlyJS}" charset="utf-8"></script>
                    <title>Plotly.NET Datavisualization</title>
                    <meta charset="UTF-8">
                    <meta name="description" content="A plotly.js graph generated with Plotly.NET">
                    <link id="favicon" rel="shortcut icon" type="image/png" href="">
                </head>
                <body>
                </body>
            </html>
            """;
        private GenericChart _chart = null!;
        #endregion 变量/常量 end

        #region      构造/析构函数 start
        public Form2()
        {
            InitializeComponent();
        }
        #endregion 构造/析构函数 end

        #region       事件处理 start
        private void Form2_Load(object sender, EventArgs e)
        {
            var fig = GetPlot1();
            _chart = GenericChart.fromFigure(fig);
            //var displayOptions = GenericChart.getDisplayOptions(chart);
            //var jsref = DisplayOptions.getPlotlyReference(displayOptions);

            var jscdn = PlotlyJSReference.NewCDN("https://cdn.bootcdn.net/ajax/libs/plotly.js/2.27.1/plotly.min.js");
            //var html = HTML.Doc(new VoidElement(), "Plotly.NET Datavisualization", "A plotly.js graph generated with Plotly.NET", "UTF-8", null, jscdn, null, null);
            //var htmlString = Giraffe.ViewEngine.RenderView.AsString.htmlDocument(html);


            var webBrowser = new WebBrowser();
            webBrowser.AllowWebBrowserDrop = false;
            webBrowser.IsWebBrowserContextMenuEnabled = false;
            //webBrowser.ScriptErrorsSuppressed = true;
            webBrowser.WebBrowserShortcutsEnabled = false;
            webBrowser.Dock = DockStyle.Fill;
            webBrowser.DocumentCompleted += WebBrowser_DocumentCompleted;
            //webBrowser.Navigate(new Uri("about:blank", UriKind.RelativeOrAbsolute));
            webBrowser.DocumentText = HtmlTemplate;
            
            this.pnl_Left.Controls.Add(webBrowser);
        }

        private void WebBrowser_DocumentCompleted(object? sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (sender is WebBrowser webBrowser)
            {
                //webBrowser.InitHtmlTemplate();
                var html = GetHtmlFromChart(_chart);
                webBrowser.LoadBody(html);
            }
        }
        #endregion 事件处理 end

        #region       私有方法 start
        private Figure GetPlot1()
        {
            LinearAxis xAxis = new LinearAxis();
            xAxis.SetValue("title", "xAxis");
            xAxis.SetValue("zerolinecolor", "#ffff");
            xAxis.SetValue("gridcolor", "#ffff");
            xAxis.SetValue("showline", true);
            xAxis.SetValue("zerolinewidth", 2);

            LinearAxis yAxis = new LinearAxis();
            yAxis.SetValue("title", "yAxis");
            yAxis.SetValue("zerolinecolor", "#ffff");
            yAxis.SetValue("gridcolor", "#ffff");
            yAxis.SetValue("showline", true);
            yAxis.SetValue("zerolinewidth", 2);

            Layout layout = new Layout();
            layout.SetValue("xaxis", xAxis);
            layout.SetValue("yaxis", yAxis);
            layout.SetValue("title", "A Figure Specified by DynamicObj");
            layout.SetValue("plot_bgcolor", "#e5ecf6");
            layout.SetValue("showlegend", true);

            Trace trace = new Trace("bar");
            trace.SetValue("x", new[] { 1, 2, 3 });
            trace.SetValue("y", new[] { 1, 3, 2 });


            var fig = Figure.create(ListModule.OfSeq(new[] { trace }), layout);
            return fig;
        }



        private string GetHtmlFromChart(GenericChart chart)
        {
            var html = GenericChart.toChartHTML(chart);
            //var html = GenericChart.toEmbeddedHTML(chart);
            //html = html.Replace("https://cdn.plot.ly/plotly-2.27.1.min.js", "https://cdn.bootcdn.net/ajax/libs/plotly.js/2.27.1/plotly.min.js");
            //var filePth = @$"D:\Case\Source4WinForm\UpperComputerTechnologyTest\UCTT.Net\1.html";
            //chart.SaveHtml(filePth);
            return html;
        }



        public string ConvertFSharpListToHtml(FSharpList<Giraffe.ViewEngine.HtmlElements.XmlNode> nodeList)
        {
            StringBuilder htmlStringBuilder = new StringBuilder();
            foreach (var node in nodeList)
            {
                //htmlStringBuilder.Append(NodeToHtml(node));
                htmlStringBuilder.Append(node.ToString());
            }
            return htmlStringBuilder.ToString();
        }

        //private string NodeToHtml(Giraffe.ViewEngine.HtmlElements.XmlNode node)
        //{
        //    if (node is Giraffe.ViewEngine.HtmlElements.Element element)
        //    {
        //        var attributes = string.Join(" ", element.Attributes.Select(attr => $"{attr.Key}=\"{attr.Value}\""));
        //        var childrenHtml = string.Concat(element.Children.Select(child => NodeToHtml(child)));
        //        return $"<{element.Tag} {attributes}>{childrenHtml}</{element.Tag}>";
        //    }
        //    else if (node is Giraffe.ViewEngine.HtmlElements.Text textNode)
        //    {
        //        return textNode.Text;
        //    }
        //    return string.Empty;
        //}
        #endregion 私有方法 end
    }

    public static class WebBrowserExtensions
    {
        /// <summary>
        /// Plotly.js 绘图库的cdn链接
        /// </summary>
        private const string PlotlyJS = "https://cdn.bootcdn.net/ajax/libs/plotly.js/2.27.1/plotly.min.js";

        /// <summary>
        /// 初始化WebBrowser控件，并加载包含Plotly.js库的html模板。
        /// </summary>
        /// <param name="webBrowser"></param>
        public static void InitHtmlTemplate(this WebBrowser webBrowser)
        {
            var head = webBrowser.Document?.GetElementsByTagName("head");
            if (head == null || webBrowser.Document?.GetElementById("ex_js") != null)
                return;

            var script = webBrowser.Document?.CreateElement("script");
            script?.SetAttribute("type", "text/javascript");
            script?.SetAttribute("id", "ex_js");
            script?.SetAttribute("src", PlotlyJS);
            script?.SetAttribute("charset", "utf-8");
            head?[0]?.AppendChild(script);

            var title = webBrowser.Document?.CreateElement("title");
            title.InnerText = "Plotly.NET Datavisualization";
            head?[0]?.AppendChild(title);

            var meta = webBrowser.Document?.CreateElement("meta");
            meta?.SetAttribute("charset", "UTF-8");
            meta?.SetAttribute("name", "description");
            meta?.SetAttribute("content", "A plotly.js graph generated with Plotly.NET");
            head?[0]?.AppendChild(meta);

            var link = webBrowser.Document?.CreateElement("link");
            link?.SetAttribute("id", "favicon");
            link?.SetAttribute("rel", "shortcut icon");
            link?.SetAttribute("type", "image/png");
            meta?.SetAttribute("href", "");
            head?[0]?.AppendChild(link);
        }

        /// <summary>
        /// 加载HtmlElement到WebBrowser的body中。
        /// </summary>
        /// <param name="webBrowser"></param>
        /// <param name="element"></param>
        public static void LoadBody(this WebBrowser webBrowser, string htmlString)
        {
            //var body = webBrowser.Document?.GetElementsByTagName("body");
            //if (body == null)
            //    return;

            //if (body.Count > 0)
            //{
            //    body[0].InnerHtml = htmlString;
            //}

            var body = webBrowser.Document?.Body;
            if (body != null)
            {
                body.InnerHtml = htmlString;
            }
        }
    }
}
